package com.kede.api.order.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.kede.api.ienum.UserMoneyType;
import com.kede.api.order.service.ISupplieManageService;
import com.kede.api.order.service.IUserService;
import com.kede.api.pojo.pay.PayCodeEnum;
import com.kede.dictenum.BoolDictEnum;
import com.kede.domain.*;
import com.kede.ienum.store.UserStoreStatusEnum;
import com.kede.pojo.PagePO;
import com.kede.pojo.ResHttp;
import com.kede.service.*;
import com.kede.utils.CollectionUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/***
 ** @Author:Pr.li
 ** @Description:
 ** @Date: create in 2023/6/8 9:51
 ***/
@Slf4j
@Service
public class SupplieManageServiceImpl implements ISupplieManageService {

    @Resource
    private StoreUserOrderService storeUserOrderService;

    @Resource
    private SuppliesStoreService suppliesStoreService;

    @Resource
    private UsersService usersService;

    @Resource
    private IUserService userManageService;

    @Resource
    private UserScoreLogService userScoreLogService;

    @Resource
    private SuppliesService suppliesService;

    @Resource
    private ZhiUserCertifiedService zhiUserCertifiedService;

    @Resource
    private PayInfoLogService payInfoLogService;

    @Value("${wx.userSuppliePaySuccesUrl}")
    private String wxpayNotifyDomain;

    private final static Integer SUPPKEY = 10;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResHttp createUserStoreOrder(StoreUserOrderDomain storeUserOrderDomain) {
        String orderno = SUPPKEY+ RandomUtil.randomNumbers(3);
        storeUserOrderDomain.setCode(Integer.valueOf(orderno));
        //查库存
        int invetory = suppliesStoreService.getInvetory(storeUserOrderDomain.getStoreId(), storeUserOrderDomain.getSupplieId());
        if(invetory <= 0){
            return ResHttp.failMsg("库存不足");
        }
        BigDecimal num = new BigDecimal(storeUserOrderDomain.getNum().toString());
        //更新用户德币
        UsersDomain users = usersService.getById(storeUserOrderDomain.getUserId());
        BigDecimal totalScore = storeUserOrderDomain.getDebi().multiply(num);
        if (users.getIntegral().compareTo(totalScore) < 0){
            return ResHttp.failMsg("用户德币不足");
        }
        SuppliesDomain supplie = suppliesService.getById(storeUserOrderDomain.getSupplieId());
        int buydnum = storeUserOrderService.getBuyedNumBySupplieIdAndUserId(storeUserOrderDomain.getSupplieId(), storeUserOrderDomain.getUserId());
        if(supplie.getBuyNum() != -1 && buydnum >= supplie.getBuyNum()){
            return ResHttp.failMsg("每人限购"+supplie.getBuyNum()+"个");
        }
        //存在需要支付的RMB
        if(storeUserOrderDomain.getMoney()!=null){
            //共需要的金额
            BigDecimal money = storeUserOrderDomain.getMoney().multiply(num);
            if(users.getUserMoney().compareTo(money) >= 0){
                //余额有剩余 就不用支付了
                userManageService.actionMoney(users.getId(),money.negate(),orderno, UserMoneyType.SHOPPING);
            }else{
                //余额不够需要扣款了
                if(users.getUserMoney().compareTo(new BigDecimal("0")) > 0){
                    //用户有余额
                    money = money.subtract(users.getUserMoney());
                    userManageService.actionMoney(users.getId(),users.getUserMoney().negate(),orderno, UserMoneyType.SHOPPING);
                }
                PayInfoLogDomain payInfoLogDomain = new PayInfoLogDomain();
                payInfoLogDomain.setCode(PayCodeEnum.OFFLINESUPPLIE.getCode());
                payInfoLogDomain.setMoney(money);
                payInfoLogDomain.setParam(JSONUtil.toJsonStr(storeUserOrderDomain));
                payInfoLogDomain.setCreateTime(LocalDateTime.now());
                payInfoLogDomain.setRemark("购买的物资编号是"+storeUserOrderDomain.getSupplieId());
                boolean save = payInfoLogService.save(payInfoLogDomain);
                if(!save){
                    return ResHttp.failMsg("兑换物资失败请联系管理员");
                }
                Map<String,String> data = new HashMap<>(2);
                data.put("payLogId",payInfoLogDomain.getId().toString());
                data.put("money",money.toString());
                data.put("snKey",payInfoLogDomain.getCode());
                data.put("url",wxpayNotifyDomain);
                return ResHttp.set(205,"去支付",data);
            }
        }
        ISupplieManageService bean = SpringUtil.getBean(ISupplieManageService.class);
        bean.doCreateUserStoreOrder(storeUserOrderDomain);

        return ResHttp.ok();
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void doCreateUserStoreOrder(StoreUserOrderDomain storeUserOrderDomain){
        UsersDomain users = usersService.getById(storeUserOrderDomain.getUserId());
        BigDecimal num = new BigDecimal(storeUserOrderDomain.getNum().toString());
        BigDecimal totalScore = storeUserOrderDomain.getDebi().multiply(num);
        BigDecimal subtract = users.getIntegral().subtract(totalScore);
        users.setIntegral(subtract);
        usersService.updateById(users);
        //添加记录
        UserScoreLogDomain scoreLogDomain = UserScoreLogDomain.builder()
                .after(users.getIntegral())
                .before(users.getIntegral().add(storeUserOrderDomain.getDebi()))
                .userId(users.getId())
                .score(new BigDecimal("-" + totalScore.toString()))
                .changeType(2)//与php 一致
                .memo("消费德币兑换门店商品").build();
        userScoreLogService.save(scoreLogDomain);

//        减去该门店改商品的库存
        Integer symnum = -storeUserOrderDomain.getNum().intValue();
        boolean b = suppliesStoreService.setInvetory(storeUserOrderDomain.getStoreId(), storeUserOrderDomain.getSupplieId(), symnum);
        storeUserOrderDomain.setCreateTime(LocalDateTime.now());
        storeUserOrderDomain.setUpdateTime(LocalDateTime.now());
        storeUserOrderDomain.setStatus(UserStoreStatusEnum.RECEVE);
        storeUserOrderService.save(storeUserOrderDomain);

    }

    @Override
    public ResHttp userSuppliePaySucces(Integer payLogId) {
        PayInfoLogDomain byId = payInfoLogService.getById(payLogId);
        byId.setResult(BoolDictEnum.TRUE.getCode());
        payInfoLogService.updateById(byId);
        StoreUserOrderDomain storeUserOrderDomain = JSONUtil.toBean(byId.getParam(), StoreUserOrderDomain.class);
        ISupplieManageService bean = SpringUtil.getBean(ISupplieManageService.class);
        bean.doCreateUserStoreOrder(storeUserOrderDomain);
        return ResHttp.ok();
    }


    @Override
    public ResHttp page(PagePO page, Integer userId) {
        List<OrderItem> orders = page.orders();
        if (CollectionUtil.Blank(orders)){
            orders.add(OrderItem.desc("create_time"));
        }
        LambdaQueryWrapper<StoreUserOrderDomain> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StoreUserOrderDomain::getUserId,userId);
        queryWrapper.eq(StoreUserOrderDomain::getUserIsdel, BoolDictEnum.FALSE.getCode());
        PagePO<StoreUserOrderDomain> page1 = storeUserOrderService.page(page, queryWrapper);
        page1.getRecords().forEach(order -> {
            SuppliesDomain supplie = suppliesService.getById(order.getSupplieId());
            ZhiUserCertifiedDomain store = zhiUserCertifiedService.getOneByUserId(order.getStoreId());
            order.setSupplie(supplie);
            order.setStore(store);
        });
        return ResHttp.okData(page1);
    }

    @Override
    public ResHttp delUserSupplieOrder(Integer orderId) {
        StoreUserOrderDomain storeUserOrderDomain = storeUserOrderService.getById(orderId);
        storeUserOrderDomain.setUserIsdel(BoolDictEnum.TRUE.getCode());
        storeUserOrderService.updateById(storeUserOrderDomain);
        return ResHttp.ok();
    }
}
